home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / documentation / tutorial / intl / concepts / example-1.1 / WordMatch.java < prev   
Encoding:
Java Source  |  1997-07-13  |  13.0 KB  |  440 lines

  1. /*
  2.  * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software
  5.  * and its documentation for NON-COMMERCIAL purposes and without
  6.  * fee is hereby granted provided that this copyright notice
  7.  * appears in all copies. Please refer to the file "copyright.html"
  8.  * for further important copyright and licensing information.
  9.  *
  10.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  11.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  12.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  13.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  14.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  15.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  16.  */
  17. /*
  18.  * @(#)WordMatch.java    1.5  25 Oct 1995 11:07:56
  19.  * @author Patrick Chan
  20.  *
  21.  * Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
  22.  *
  23.  * Permission to use, copy, modify, and distribute this software
  24.  * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
  25.  * without fee is hereby granted. 
  26.  * Please refer to the file http://java.sun.com/copy_trademarks.html
  27.  * for further important copyright and trademark information and to
  28.  * http://java.sun.com/licensing.html for further important licensing
  29.  * information for the Java (tm) Technology.
  30.  * 
  31.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  32.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  33.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  34.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  35.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  36.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  37.  * 
  38.  * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
  39.  * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
  40.  * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
  41.  * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
  42.  * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
  43.  * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
  44.  * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
  45.  * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
  46.  * HIGH RISK ACTIVITIES.
  47.  */
  48.  
  49. import java.awt.*;
  50. import java.applet.*;
  51. import java.awt.*;
  52. import java.awt.event.*;
  53. import java.util.*;
  54.  
  55. public class WordMatch extends Applet 
  56.         implements ActionListener, ItemListener {
  57.  
  58.     // Number of displayed cards and words.
  59.     int numCards = 4;
  60.  
  61.     // Currently selected language.
  62.     int curLanguage;
  63.  
  64.     // card[i] refers to the i'th word.
  65.     int cards[];
  66.  
  67.     // words[i] refers to the i'th card.
  68.     int words[];
  69.  
  70.     // Currently selected card.
  71.     int curCard;
  72.  
  73.     // The components.
  74.     Box soundBox;
  75.     List languageList = new List();
  76.     Label statusBar = new Label("Ready");
  77.     Button scoreButton;
  78.     Box[] cardBoxes;
  79.     Box[] wordBoxes;
  80.  
  81.     // If true, the user has successfully matched all the words.
  82.     boolean done;
  83.     
  84.     // links[i] == j -> cards[i] is linked to words[j].
  85.     int links[];
  86.  
  87.     // Images of pictures.  There is one image for each different word.
  88.     Image images[];
  89.  
  90.     // The dimensions of the images.  They must all be the same size.
  91.     int imageW, imageH;
  92.  
  93.     int numWords;
  94.     String[] languages;
  95.     String[][] dictionary;
  96.  
  97.     // Width of language list.
  98.     int languageListW = 120;
  99.  
  100.     // Used to layout the components.
  101.     int gap = 10;
  102.  
  103.     /**
  104.      * Initialize the applet. Resize and load images.
  105.      */
  106.     public void init() {
  107.         imageW = Integer.parseInt(getParameter("image-w"));
  108.         imageH = Integer.parseInt(getParameter("image-h"));
  109.  
  110.         // Count number of languages
  111.         for (int i=1; ; i++) {
  112.             if (getParameter("language"+i) == null) {
  113.                 languages = new String[i-1];
  114.                 dictionary = new String[i-1][];
  115.                 break;
  116.             }
  117.         }
  118.  
  119.         // Count total number of words, based on the first language.
  120.         for (int i=0; i<languages.length; i++) {
  121.         StringTokenizer st = new StringTokenizer(
  122.                 getParameter("language"+(i+1)), "|");
  123.  
  124.             dictionary[i] = new String[st.countTokens()-1];
  125.             languages[i] = st.nextToken();
  126.             languageList.addItem(languages[i]);
  127.             
  128.         for (int j=0; j<dictionary[i].length; j++) {
  129.                 dictionary[i][j] = st.nextToken();
  130.         }
  131.         }
  132.         numWords = dictionary[0].length;
  133.  
  134.         // Create data structures.
  135.         cards = new int[numCards];
  136.         cardBoxes = new Box[numCards];
  137.         words = new int[numCards];
  138.         wordBoxes = new Box[numCards];
  139.         links = new int[numCards];
  140.         images = new Image[numWords];
  141.         curLanguage = 0;
  142.  
  143.         // Load the images.
  144.         for (int i=0; i<numWords; i++) {
  145.         images[i] = getImage(getCodeBase(), "rsrc/"
  146.         + dictionary[0][i] + ".gif");
  147.         }
  148.  
  149.         // Layout the components.  Use absoluting positioning.
  150.         setLayout(null);
  151.  
  152.         // Setup the score button.
  153.         scoreButton = new Button("Score");
  154.         add(scoreButton);
  155.         Dimension d = scoreButton.getPreferredSize();
  156.         scoreButton.setBounds(0, getSize().height-d.height, 
  157.             languageListW, d.height);
  158.         scoreButton.addActionListener(this);
  159.  
  160.         // Setup the language list.
  161.         add(languageList);
  162.         languageList.setBounds(0, 0, 
  163.             languageListW, getSize().height-d.height);
  164.         languageList.addItemListener(this);
  165.         languageList.select(curLanguage);
  166.  
  167.     // Setup the status bar.
  168.         add(statusBar);
  169.         statusBar.setBounds(languageListW+2*gap, getSize().height-d.height, 
  170.             getSize().width-languageListW-2*gap, d.height);
  171.  
  172.         // Setup sound box.
  173.         soundBox = new Box(getImage(getCodeBase(), "rsrc/sound.gif"));
  174.         add(soundBox);
  175.         soundBox.addItemListener(this);
  176.         soundBox.setBounds(0, 0, 32, 32);
  177.  
  178.     Font f = new Font("SansSerif", Font.PLAIN, 16);
  179.         for (int i=0; i<numCards; i++) {
  180.             // Setup the picture cards.
  181.             cardBoxes[i] = new Box(images[cards[i]]);
  182.             add(cardBoxes[i]);
  183.             cardBoxes[i].setBounds(languageListW+2*gap, 
  184.                 i*(imageH+gap), imageW, imageH);
  185.             cardBoxes[i].addItemListener(this);
  186.             cardBoxes[i].select(i == 0);
  187.  
  188.             // Setup up the word boxes.
  189.             wordBoxes[i] = new Box(dictionary[curLanguage][words[i]], f);
  190.             add(wordBoxes[i]);
  191.             wordBoxes[i].setBounds(languageListW+4*gap+2*imageW, 
  192.                 i*(imageH+gap), getSize().width, imageH);
  193.             wordBoxes[i].addItemListener(this);
  194.         }
  195.  
  196.         moveSoundBox();
  197.         newRound();
  198.     }
  199.  
  200.     /**
  201.      * Paint the screen.
  202.      */
  203.     public void paint(Graphics g) {
  204.         int x, y;
  205.  
  206.         // Paint links.
  207.         g.setColor(Color.black);
  208.         for (int i=0; i<numCards; i++) {
  209.             if (links[i] >= 0) {
  210.                 Point pt1 = cardBoxes[i].getLocation();
  211.                 Point pt2 = wordBoxes[links[i]].getLocation();
  212.  
  213.                 pt1.translate(imageW+gap, imageH/2);
  214.                 pt2.translate(-gap, imageH/2);
  215.  
  216.                 g.drawLine(pt1.x, pt1.y, pt2.x, pt2.y);
  217.             }
  218.     }
  219.     }
  220.  
  221.     public void itemStateChanged(ItemEvent evt) {
  222.         if (!done) {
  223.             statusBar.setText(null);
  224.         }
  225.         if (evt.getSource() == soundBox) {
  226.         play(getCodeBase(), "rsrc/" + dictionary[0][cards[curCard]] 
  227.         + "." + languages[curLanguage] + ".au");
  228.         }
  229.  
  230.         // Was the event fired from one of the picture cards?
  231.         for (int i=0; i<cardBoxes.length; i++) {
  232.             if (cardBoxes[i] == evt.getSource()) {
  233.             // In card box.
  234.                 cardBoxes[curCard].select(false);
  235.                 cardBoxes[i].select(true);
  236.                 curCard = i;
  237.  
  238.                 moveSoundBox();
  239.         repaint();
  240.                 break;
  241.         }
  242.         } 
  243.  
  244.         // Was the event fired from one of the words?
  245.         for (int i=0; i<wordBoxes.length; i++) {
  246.             if (wordBoxes[i] == evt.getSource()) {
  247.         // Break an old link if necessary.
  248.         for (int j=0; j<numCards; j++) {
  249.             if (links[j] == i) {
  250.             links[j] = -1;
  251.             }
  252.         }
  253.         links[curCard] = i;
  254.         repaint();
  255.             }
  256.         } 
  257.  
  258.         // Was the event fired from the language list?
  259.         if (evt.getSource() == languageList) {
  260.             curLanguage = languageList.getSelectedIndex();
  261.             for (int i=0; i<wordBoxes.length; i++) {
  262.                 wordBoxes[i].setText(dictionary[curLanguage][words[i]]);
  263.             }
  264.         }
  265.     }
  266.  
  267.     void moveSoundBox() {
  268.     // Move the sound box.
  269.     Point pt = cardBoxes[curCard].getLocation();
  270.     soundBox.setLocation(
  271.         pt.x+imageW-soundBox.getSize().width/2, 
  272.         pt.y+imageH-soundBox.getSize().height/2);
  273.     }
  274.  
  275.     public void actionPerformed(ActionEvent evt) {
  276.         if (evt.getSource() == scoreButton) {
  277.             if (done) {
  278.             scoreButton.setLabel("Score");
  279.                 newRound();
  280.                 repaint();
  281.             }
  282.             int count = 0;
  283.             for (int i=0; i<numCards; i++) {
  284.                 if (links[i] == -1) {
  285.                     statusBar.setText("You have not yet matched all the words.");
  286.                     return;
  287.                 }
  288.                 if (cards[i] == words[links[i]]) {
  289.                     count++;
  290.                 }
  291.             }
  292.             if (count == numCards) {            
  293.         statusBar.setText("Congratulations, they're all right!");
  294.                 done = true;
  295.                 scoreButton.setLabel("New Game");
  296.             } else if (count == 1) {
  297.         statusBar.setText("There is only 1 correct match.");
  298.             } else if (count == 0) {
  299.         statusBar.setText("There are no correct matches.");
  300.             } else {
  301.         statusBar.setText("There are " + count + " correct matches.");
  302.             }
  303.         }
  304.     }
  305.  
  306.     /**
  307.      * Starts a new round.
  308.      */
  309.     public void newRound() {
  310.         boolean[] picked = new boolean[numWords];
  311.  
  312.         statusBar.setText(null);
  313.         done = false;
  314.  
  315.         // Pick new cards.
  316.         for (int i=0; i<numCards; i++) {
  317.         while (true) {
  318.                 int r = (int)Math.floor(Math.random() * numWords);
  319.  
  320.                 if (!picked[r]) {
  321.                 cards[i] = r;
  322.                 words[i] = r;
  323.                 links[i] = -1;
  324.                 picked[r] = true;
  325.                     break;
  326.                 }
  327.             }
  328.     }
  329.  
  330.         // Scramble the pictures
  331.         for (int i=0; i<100; i++) {
  332.         int r = (int)Math.floor(Math.random() * numCards);
  333.             int t = cards[r];
  334.  
  335.             cards[r] = cards[i%numCards];
  336.             cards[i%numCards] = t;
  337.         }
  338.  
  339.  
  340.     // Initialize the new pictures and words.
  341.     for (int i=0; i<numCards; i++) {
  342.         cardBoxes[i].setImage(images[cards[i]]);
  343.         wordBoxes[i].setText(dictionary[curLanguage][words[i]]);
  344.     }
  345.     }
  346.  
  347.  
  348.     // Added by K.A. Smith 10/25/95 
  349.     public String getAppletInfo() {
  350.        return "Author: Patrick Chan\nVersion: 2.0, June 1 1997";
  351.     }
  352. }
  353.  
  354. class Box extends Canvas implements ItemSelectable {
  355.     Font font;
  356.     Image image;
  357.     String string;
  358.     boolean selected;
  359.  
  360.     Box(Image image) {
  361.         this.image = image;
  362.         addMouseListener(new MouseEventHandler());
  363.     }
  364.  
  365.     Box(String string, Font f) {
  366.         this.string = string;
  367.         font = f;
  368.         addMouseListener(new MouseEventHandler());
  369.     }
  370.  
  371.     public void select(boolean s) {
  372.         selected = s;
  373.         repaint();
  374.     }
  375.  
  376.     public void setText(String s) {
  377.         string = s;
  378.         repaint();
  379.     }
  380.  
  381.     public void setImage(Image i) {
  382.         image = i;
  383.         repaint();
  384.     }
  385.  
  386.     public Object[] getSelectedObjects() {
  387.     Object[] result;
  388.         if (selected) {
  389.             result = new Object[1];
  390.             result[0] = this;
  391.         } else {
  392.             result = new Object[0];
  393.         }
  394.         return result;
  395.     }
  396.  
  397.     public void paint(Graphics g) {
  398.         int w = getSize().width;
  399.         int h = getSize().height;
  400.  
  401.         // If it's an image, paint it.
  402.         if (image != null) {
  403.             g.drawImage(image, 0, 0, this);
  404.  
  405.             if (selected) {
  406.                 g.setColor(Color.red);
  407.                 g.drawRect(0, 0, w-1, h-1);
  408.             }
  409.         }
  410.         // If it's a string, paint it.
  411.         if (string != null) {
  412.             g.setFont(font);
  413.             FontMetrics fontM = g.getFontMetrics();
  414.  
  415.         g.setColor(Color.black);
  416.         g.drawString(string, 0, (h-fontM.getHeight())/2+fontM.getAscent());
  417.         }
  418.     }
  419.  
  420.     class MouseEventHandler extends MouseAdapter {
  421.         public void mousePressed(MouseEvent evt) {
  422.         ItemEvent e = new ItemEvent(Box.this, 
  423.             ItemEvent.ITEM_STATE_CHANGED, string, ItemEvent.SELECTED);
  424.     
  425.         if (ItemListener != null) {
  426.             ItemListener.itemStateChanged(e);
  427.         }
  428.         }
  429.     }
  430.  
  431.     ItemListener ItemListener;
  432.     public synchronized void addItemListener(ItemListener l) {
  433.     ItemListener = AWTEventMulticaster.add(ItemListener, l);
  434.     }
  435.  
  436.     public synchronized void removeItemListener(ItemListener l) {
  437.     ItemListener = AWTEventMulticaster.remove(ItemListener, l);
  438.     }
  439. }
  440.